/*
 * Copyright Webfunny Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.webfunny.android.sample;

import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.navigation.fragment.NavHostFragment;
import com.webfunny.android.sample.databinding.FragmentSecondBinding;
import com.webfunny.rum.WebfunnyRum;
import io.opentelemetry.android.instrumentation.RumScreenName;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.events.EventEmitter;
import io.opentelemetry.api.events.EventEmitterProvider;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.logs.internal.SdkEventEmitterProvider;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

@RumScreenName("Fragment 2️⃣")
public class SecondFragment extends Fragment {

    private final ScheduledExecutorService spammer = Executors.newSingleThreadScheduledExecutor();
    private final MutableLiveData<String> spanCountLabel = new MutableLiveData<>();
    private final AtomicLong spans = new AtomicLong(0);

    private ScheduledFuture<?> spamTask;

    private FragmentSecondBinding binding;
    private Tracer sampleAppTracer;

    private Span customChromeTabTimer;

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        sampleAppTracer = WebfunnyRum.getInstance().getOpenTelemetry().getTracer("sampleAppTracer");
        binding = FragmentSecondBinding.inflate(inflater, container, false);
        return binding.getRoot();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (customChromeTabTimer != null) {
            customChromeTabTimer.end();
            customChromeTabTimer = null;
        }
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        binding.setLifecycleOwner(getViewLifecycleOwner());
        binding.setSecondFragment(this);

        resetLabel();

        binding.buttonSecond.setOnClickListener(
                v -> {
                    // an example of using the OpenTelemetry API directly to generate a 100% custom
                    // span.
                    Span span =
                            sampleAppTracer
                                    .spanBuilder("buttonClicked")
                                    .setAttribute("buttonName", "backButton")
                                    .startSpan();
                    try (Scope s = span.makeCurrent()) {
                        NavHostFragment.findNavController(SecondFragment.this)
                                .navigate(R.id.action_SecondFragment_to_FirstFragment);
                    } finally {
                        span.end();
                    }
                });
        binding.buttonToWebview.setOnClickListener(
                v -> {
                    WebfunnyRum.getInstance()
                            .addRumEvent("this span will be ignored", Attributes.empty());
                    emitEvent(WebfunnyRum.getInstance(), "SecondFragment", "toWebViewClick");

                    NavHostFragment.findNavController(SecondFragment.this)
                            .navigate(R.id.action_SecondFragment_to_webViewFragment);
                });

        binding.buttonToShopWebview.setOnClickListener(
                v -> {
                    NavHostFragment.findNavController(SecondFragment.this)
                            .navigate(R.id.action_SecondFragment_to_shopWebViewFragment);
                });

        binding.buttonToCustomTab.setOnClickListener(
                v -> {
                    String url = "https://frontend-us.splunko11y.com/";
                    customChromeTabTimer =
                            WebfunnyRum.getInstance().startWorkflow("Visit to Chrome Custom Tab");
                    new CustomTabsIntent.Builder()
                            .setColorScheme(CustomTabsIntent.COLOR_SCHEME_DARK)
                            .setStartAnimations(
                                    getContext(),
                                    android.R.anim.slide_in_left,
                                    android.R.anim.slide_out_right)
                            .setExitAnimations(
                                    getContext(),
                                    android.R.anim.slide_out_right,
                                    android.R.anim.slide_in_left)
                            .build()
                            .launchUrl(this.getContext(), Uri.parse(url));
                });

        binding.buttonSpam.setOnClickListener(v -> toggleSpam());

        binding.buttonFreeze.setOnClickListener(
                v -> {
                    Span appFreezer = WebfunnyRum.getInstance().startWorkflow("app freezer");
                    try {
                        for (int i = 0; i < 20; i++) {
                            Thread.sleep(1_000);
                            appFreezer.addEvent("still sleeping");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        appFreezer.end();
                    }
                });
        binding.drawSlowly.setOnClickListener(
                v -> {
                    boolean slowlyNow = binding.animatedView.toggleSlowly();
                    if (slowlyNow) {
                        binding.drawSlowly.setText(R.string.draw_speed_normally);
                    } else {
                        binding.drawSlowly.setText(R.string.draw_speed_slowly);
                    }
                });
        binding.buttonWork.setOnClickListener(
                v -> {
                    Span hardWorker =
                            WebfunnyRum.getInstance().startWorkflow("main thread working hard");
                    Random random = new Random();
                    long startTime = System.currentTimeMillis();
                    while (true) {
                        random.nextDouble();
                        if (System.currentTimeMillis() - startTime > 20_000) {
                            break;
                        }
                    }
                    hardWorker.end();
                });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }

    public LiveData<String> getSpanCountLabel() {
        return spanCountLabel;
    }

    private void toggleSpam() {
        if (spamTask == null) {
            resetLabel();
            spamTask =
                    spammer.scheduleAtFixedRate(this::createSpamSpan, 0, 50, TimeUnit.MILLISECONDS);
            binding.buttonSpam.setText(R.string.stop_spam);
        } else {
            spamTask.cancel(false);
            spamTask = null;
            binding.buttonSpam.setText(R.string.start_spam);
        }
    }

    private void resetLabel() {
        spans.set(0);
        updateLabel();
    }

    private void updateLabel() {
        int count = (int) spans.get();
        spanCountLabel.postValue(
                getResources().getQuantityString(R.plurals.spam_status, count, count));
    }

    private void createSpamSpan() {
        sampleAppTracer
                .spanBuilder("Spam Span no. " + spans.incrementAndGet())
                .setAttribute("number", spans.get())
                .startSpan()
                .end();
        updateLabel();
    }

    public static void emitEvent(WebfunnyRum webfunnyRum, String eventDomain, String eventName) {
        EventEmitterProvider eventEmitterProvider =
                SdkEventEmitterProvider.create(
                        ((OpenTelemetrySdk) webfunnyRum.getOpenTelemetry()).getSdkLoggerProvider());
        EventEmitter eventEmitter =
                eventEmitterProvider
                        .eventEmitterBuilder("test")
                        .setEventDomain(eventDomain)
                        .build();
        eventEmitter.emit(eventName, Attributes.empty());
    }
}
